#include "global_vars.h"
void adjust_position(config_info *config);

void parse_config_file(int self_id, const char * config_file_name, char am_i_leader, int num_proposers) {
	char *match;
	char flag;

	config_sample = (config_info*) malloc(sizeof(config_info));
	config_sample->self_id = self_id;
	config_sample->num_proposers = num_proposers;

	match = "node";
	flag = 'n';
	get_ip_port(config_file_name, get_config_info(), match, flag);

	match = "leader";
	flag = 'l';
	get_ip_port(config_file_name, get_config_info(), match, flag);
	adjust_position(get_config_info());

	if (am_i_leader == 1)
		create_tcp_server_socket_for_star(get_config_info()->l.IP, get_config_info()->l.port, get_config_info()->num_nodes, get_config_info()->l.sid);
	else {
		create_ring(get_config_info());
		connect_to_leader(get_config_info());
		//		setsock_nonblock(config_sample->nodes[self_id].self_sid);
		//		setsock_nonblock(config_sample->nodes[self_id].successor_sid);
	}
}

void get_ip_port(const char* config_file, config_info * config, const char * match, char flag) {

	FILE * fp;
	char line[STRING_SIZE];
	char word[STRING_SIZE];
	int last_index = -1, node_counter = 0;

	fp = fopen(config_file, "r");
	assert(fp != NULL);
	while (!feof(fp)) {
		if (fgets(line, STRING_SIZE, fp) != 0) {
			last_index = get_substr(0, strlen(line) - 1, line, word);

			if (strcmp(word, match) == 0) {

				last_index = get_substr(last_index + 1, strlen(line) - 1, line, word);
				if (flag == 'n')
					config->nodes[node_counter].self_id = atoi(word);
				if (flag == 'l')
					config->l.self_id = atoi(word);

				last_index = get_substr(last_index + 1, strlen(line) - 1, line, word);
				if (flag == 'n')
					memcpy(config->nodes[node_counter].IP, word, strlen(word));
				if (flag == 'l')
					memcpy(config->l.IP, word, strlen(word));

				last_index = get_substr(last_index + 1, strlen(line) - 1, line, word);
				if (flag == 'n')
					config->nodes[node_counter].port = atoi(word);
				if (flag == 'l')
					config->l.port = atoi(word);

				node_counter++;
			}
		}
	}
	if (flag == 'n')
		config->num_nodes = node_counter;

	fclose(fp);
}

int get_substr(int start_index, int end_index, char * source, char * result_to_return) {
	int i = 0, j = 0;

	memset(result_to_return, '\0', STRING_SIZE);

	for (i = start_index; i < end_index; i++) {
		if (source[i] == SPACE)
			break;
		result_to_return[j] = source[i];
		j++;
	}
	return i;
}

void create_ring(config_info *config) {

	int successor_id = config->self_id + 1;
	int self_id = config->self_id;

	if (self_id == 0) {
		printf("Creating socket to send msg to successor on the ring ip: %s port: %d\n", config->nodes[successor_id].IP, config->nodes[successor_id].port);
		config->nodes[self_id].successor_sid = create_tcp_client_socket(config->nodes[successor_id].IP, config->nodes[successor_id].port);
		config->nodes[self_id].self_sid = create_tcp_server_socket(config->nodes[self_id].IP, config->nodes[self_id].port);

	} else {

		if (self_id == config->num_nodes - 1)
			successor_id = 0;

		printf("self ip: %s.  SUCC ip: %s\n", config->nodes[self_id].IP, config->nodes[successor_id].IP);
		config->nodes[self_id].self_sid = create_tcp_server_socket(config->nodes[self_id].IP, config->nodes[self_id].port);
		printf("Creating socket to send msg to successor on the ring ip: %s port: %d\n", config->nodes[successor_id].IP, config->nodes[successor_id].port);
		config->nodes[self_id].successor_sid = create_tcp_client_socket(config->nodes[successor_id].IP, config->nodes[successor_id].port);

	}

}

void connect_to_leader(config_info *config) {
	config->nodes[config->self_id].leader_sid = create_tcp_client_socket(config->l.IP, config->l.port);
}
config_info * get_config_info() {
	return config_sample;

}

void adjust_position(config_info *config) {
	int i, j;
	char temp_ip[16];
	int temp_id, temp_port;

	for (i = 0; i < config->num_nodes; i++) {
		for (j = 0; j < config->num_nodes; j++) {
			//			int position = config->nodes[i].self_id;

			if (j == config->nodes[i].self_id) {
				int position = j;
				temp_id = config->nodes[position].self_id;
				memcpy(temp_ip, config->nodes[position].IP, 16);
				temp_port = config->nodes[position].port;

				config->nodes[position].self_id = config->nodes[i].self_id;
				memcpy(config->nodes[position].IP, config->nodes[i].IP, 16);
				config->nodes[position].port = config->nodes[i].port;

				config->nodes[i].self_id = temp_id;
				memcpy(config->nodes[i].IP, temp_ip, 16);
				config->nodes[i].port = temp_port;
			}
		}
	}
}
